{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating new surrogate models for GPyOpt\n",
    "\n",
    "### Written by Javier Gonzalez and Andrei Paleyes.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can create and use your own surrogate models functions in GPyOpt. To do it just complete the following template."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Copyright (c) 2016, the GPyOpt Authors\n",
    "# Licensed under the BSD 3-clause license (see LICENSE.txt)\n",
    "\n",
    "from GPyOpt.models import BOModel\n",
    "import numpy as np\n",
    "\n",
    "class NewModel(BOModel):\n",
    "   \n",
    "    \"\"\"\n",
    "    General template to create a new GPyOPt surrogate model\n",
    "\n",
    "    :param normalize Y: wheter the outputs are normalized (default, false)\n",
    "\n",
    "    \"\"\"\n",
    "\n",
    "    # SET THIS LINE TO True of False DEPENDING IN THE ANALYTICAL GRADIENTS OF THE PREDICTIONS ARE AVAILABLE OR NOT\n",
    "    analytical_gradient_prediction = False\n",
    "\n",
    "    def __init__(self, normalize_Y=True, **kwargs ):\n",
    "\n",
    "        # ---\n",
    "        # ADD TO self... THE REST OF THE PARAMETERS OF YOUR MODEL\n",
    "        # ---\n",
    "        \n",
    "        self.normalize_Y = normalize_Y\n",
    "        self.model = None\n",
    "\n",
    "    def _create_model(self, X, Y):\n",
    "        \"\"\"\n",
    "        Creates the model given some input data X and Y.\n",
    "        \"\"\"\n",
    "        self.X = X\n",
    "        self.Y = Y\n",
    "        \n",
    "        # ---\n",
    "        # ADD TO self.model THE MODEL CREATED USING X AND Y.\n",
    "        # ---\n",
    "        \n",
    "        \n",
    "    def updateModel(self, X_all, Y_all, X_new, Y_new):\n",
    "        \"\"\"\n",
    "        Updates the model with new observations.\n",
    "        \"\"\"\n",
    "        self.X = X_all\n",
    "        self.Y = Y_all\n",
    "        \n",
    "        if self.normalize_Y:\n",
    "            Y_all = (Y_all - Y_all.mean())/(Y_all.std())\n",
    "        \n",
    "        if self.model is None: \n",
    "            self._create_model(X_all, Y_all)\n",
    "        else:\n",
    "            pass\n",
    "            # ---\n",
    "            # AUGMENT THE MODEL HERE AND REUPDATE THE HIPER-PARAMETERS\n",
    "            # ---\n",
    "                 \n",
    "    def predict(self, X):\n",
    "        \"\"\"\n",
    "        Preditions with the model. Returns posterior means m and standard deviations s at X. \n",
    "        \"\"\"\n",
    "\n",
    "        # ---\n",
    "        # IMPLEMENT THE MODEL PREDICTIONS HERE (outputs are numpy arrays with a point per row)\n",
    "        # ---\n",
    "        \n",
    "        return m, s\n",
    "    \n",
    "    def get_fmin(self):\n",
    "        return self.model.predict(self.X).min()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
